package com.authine.cloudpivot.ext.applicationservice.report;

import com.alibaba.cola.dto.SingleResponse;
import com.alibaba.cola.exception.BizException;
import com.alibaba.cola.exception.Exceptions;
import com.alibaba.fastjson.JSONObject;
import com.authine.cloudpivot.ext.applicationservice.InquiryService;
import com.authine.cloudpivot.ext.constants.AppConst;
import com.authine.cloudpivot.ext.constants.ModelConst;
import com.authine.cloudpivot.ext.constants.PlatformConst;
import com.authine.cloudpivot.ext.dto.system.OrganizationDto;
import com.authine.cloudpivot.ext.dto.system.UserDto;
import com.authine.cloudpivot.ext.enums.inquiry.QuotationStatusEnum;
import com.authine.cloudpivot.ext.model.ReportRecord;
import com.authine.cloudpivot.ext.utils.BigDecimalUtils;
import com.authine.cloudpivot.ext.utils.BoServiceUtils;
import com.authine.cloudpivot.ext.utils.JdbcTemplateUtils;
import com.authine.cloudpivot.ext.utils.system.OrgUtils;
import com.authine.cloudpivot.ext.utils.system.ReportUtils;
import com.authine.cloudpivot.ext.utils.system.UserUtils;
import com.authine.common.util.DateUtils;
import com.authine.mvp.app.launcher.domain.SelectorFormat;
import com.authine.mvp.app.launcher.dto.bo.response.BO;
import com.authine.mvp.app.launcher.dto.bo.response.BOList;
import com.authine.mvp.app.launcher.dto.errorcode.ErrorCodeEnum;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import javax.ws.rs.POST;
import javax.ws.rs.Path;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

import static com.authine.hermes.app.launcher.service.ApplicationServiceFoundation.CUSTOM_SERVICE;

/**
 * @ClassName PricingReportService
 * @Description: 我的核价导出
 * @Author fj
 * @Date 2021/9/14
 * @Version V1.0
 **/
@Path("PricingReportService")
@Slf4j
public class PricingReportService {
    private static final InquiryService inquiryService = new InquiryService();

    /**
     * 我的核价-核价列表-导出/我的核价-核价历史-导出
     *
     * @param record 报表导出数据
     * @return 导出
     */
    @Path("priceGoodsReport")
    @POST
    @Operation(summary = "我的核价-核价列表-导出/我的核价-核价历史-导出", tags = CUSTOM_SERVICE)
    public SingleResponse<BO> priceGoodsReport(@Parameter ReportRecord record) {
        if (StringUtils.isEmpty(record.getType())) {
            throw new BizException("报表导出类型不正确");
        }
        if (StringUtils.isEmpty(record.getCode())) {
            throw new BizException("报表导出文件不正确");
        }
        List<Map<String, Object>> reportList = Lists.newArrayList();// 报表数据
        // 通过报价商品id获取报价商品列表
        SingleResponse<BOList> inquiryBOList = BoServiceUtils.findListByIn(ModelConst.T_INQUIRY, "id", record.getIds());
        log.info("-----------------------通过询价单id获取询价单列表：{}------------------------", JSONObject.toJSONString(inquiryBOList));
        if (inquiryBOList.getData().getTotal() > 0) {
            SingleResponse<BOList> inquiryGoodsBOList;
            SingleResponse<BOList> quotationGoodsBOList;
            SingleResponse<BOList> quotedBOList;
            Map<String, Object> dataMap;
            Optional<Map<String, Object>> minPrice;
            Optional<Map<String, Object>> minAmount;
            for (Map<String, Object> inquiryMap : inquiryBOList.getData().getData()) {
                // 通过询价单id获取询价商品列表
                inquiryGoodsBOList = BoServiceUtils.findListBySimple(ModelConst.T_INQUIRY_GOODS, "inquiry_id", inquiryMap.get("id"));
                log.info("-----------------------通过询价单id获取询价商品列表：{}------------------------", JSONObject.toJSONString(inquiryGoodsBOList));
                // 询价商品id正序
                inquiryGoodsBOList.getData().getData().sort(Comparator.comparing(goodsSortMap -> Long.parseLong(String.valueOf(goodsSortMap.get("id")))));
                // 通过询价商品id获取报价商品列表
                for (Map<String, Object> inquiryGoodsMap : inquiryGoodsBOList.getData().getData()) {
                    quotationGoodsBOList = BoServiceUtils.findListBySimple(ModelConst.T_QUOTATION_GOODS, "inquiry_goods_id", inquiryGoodsMap.get("id"));
                    log.info("-----------------------通过询价商品id获取报价商品列表：{}------------------------", JSONObject.toJSONString(quotationGoodsBOList));
                    // 获取所有已报价的报价商品id
                    List<String> quotedId = quotationGoodsBOList.getData().getData().stream()
                            .filter(quotationMap -> quotationMap.get("pretax_price") != null)
                            .map(quotationMap -> String.valueOf(quotationMap.get("id")))
                            .collect(Collectors.toList());
                    log.info("-----------------------所有已报价的报价商品id：{}------------------------", quotedId);
                    for (Map<String, Object> quotationMap : quotationGoodsBOList.getData().getData()) {
                        String id = String.valueOf(quotationMap.get("id"));
                        quotedId.remove(id);
                        // 增加判断，避免使用in查询报错
                        if (!CollectionUtils.isEmpty(quotedId)) {
                            // 获取所有已报价的报价商品列表
                            quotedBOList = BoServiceUtils.findListByIn(ModelConst.T_QUOTATION_GOODS, "id", quotedId);
                            // 获取其他组织报的最低价（加上filter过滤条件，避免脏数据导致报错）
                            minPrice = quotedBOList.getData().getData().stream()
                                    .filter(quotation -> quotation.get("pretax_price") != null)
                                    .min(Comparator.comparing(quotation -> (BigDecimal) quotation.get("pretax_price")));
                            minAmount = quotedBOList.getData().getData().stream()
                                    .filter(quotation -> quotation.get("pretax_amount") != null)
                                    .min(Comparator.comparing(quotation -> (BigDecimal) quotation.get("pretax_amount")));
                        } else {
                            minPrice = Optional.empty();
                            minAmount = Optional.empty();
                        }

                        dataMap = Maps.newHashMap();
                        dataMap.put("id", String.valueOf(inquiryMap.get("id")));
                        dataMap.put("inquiryGoodsId", String.valueOf(inquiryGoodsMap.get("id")));
                        dataMap.put("brand", String.valueOf(inquiryGoodsMap.get("brand")));
                        dataMap.put("name", String.valueOf(inquiryGoodsMap.get("name")));
                        dataMap.put("model", String.valueOf(inquiryGoodsMap.get("model")));
                        dataMap.put("time", String.valueOf(inquiryMap.get("createdTime")));
                        dataMap.put("vendorName", quotationMap.get("vendor_organization_name") == null ? "" : String.valueOf(quotationMap.get("vendor_organization_name")));
                        dataMap.put("customerName", inquiryMap.get("member_name") == null ? "" : String.valueOf(inquiryMap.get("member_name")));
                        dataMap.put("prePrice", quotationMap.get("pretax_price") == null ? 0d : ((BigDecimal) quotationMap.get("pretax_price")).doubleValue());
                        dataMap.put("preAmount", quotationMap.get("pretax_amount") == null ? 0d : ((BigDecimal) quotationMap.get("pretax_amount")).doubleValue());
                        dataMap.put("minPrice", minPrice.map(minPriceMap -> BigDecimalUtils.isNull(minPriceMap.get("pretax_price")).doubleValue()).orElse(0d));
                        dataMap.put("minAmount", minAmount.map(minAmountMap -> BigDecimalUtils.isNull(minAmountMap.get("pretax_amount")).doubleValue()).orElse(0d));
                        dataMap.put("description", inquiryGoodsMap.get("description") == null ? "" : String.valueOf(inquiryGoodsMap.get("description")));
                        dataMap.put("isPicketed", QuotationStatusEnum.QUOTATION_5_PICKETED.getCode().equals(String.valueOf(quotationMap.get("quotation_goods_status"))) ? "是" : "否");
                        quotedId.add(id);
                        reportList.add(dataMap);
                    }
                }
            }
        }
        return ReportUtils.exportReport(record.getCode(), record.getType(), reportList);
    }

    /**
     * 核价详情-导出全部报价-通用核价单模板(未税)
     *
     * @param record 报表导出数据
     * @return 导出
     */
    @Path("gomroQuotationReport")
    @POST
    @Operation(summary = "核价详情-导出全部报价-通用核价单模板，根据code区分未税和含税", tags = CUSTOM_SERVICE)
    public SingleResponse<BO> gomroQuotationReport(@Parameter ReportRecord record) {
        if (StringUtils.isEmpty(record.getType())) {
            throw new BizException("报表导出类型不正确");
        }
        if (StringUtils.isEmpty(record.getCode())) {
            throw new BizException("报表导出文件不正确");
        }

        // 获取询价单id
        if (record.getParam().get("inquiryId") == null) {
            throw new BizException("询价单id不能为空");
        }
        String inquiryId = String.valueOf(record.getParam().get("inquiryId"));
        List<Map<String, Object>> reportList = Lists.newArrayList();// 报表数据

        // 通过询价单id获取询价信息
        SingleResponse<BO> inquiryBO = BoServiceUtils.loadBo(inquiryId, false, ModelConst.T_INQUIRY, true);
        log.info("-----------------------通过询价单id获取询价单详情：{}------------------------", inquiryBO);
        if (!inquiryBO.isSuccess()) {
            Exceptions.throwBizException(ErrorCodeEnum.BO_GET_ERROR);
        }

        // 通过询价单id获取询价商品信息
        SingleResponse<BOList> inquiryGoodsBOList = BoServiceUtils.findListBySimple(ModelConst.T_INQUIRY_GOODS, "inquiry_id", inquiryId);
        log.info("-----------------------通过询价单id获取询价商品列表：{}------------------------", inquiryGoodsBOList);
        if (!inquiryGoodsBOList.isSuccess() || inquiryGoodsBOList.getData().getTotal() == 0) {
            Exceptions.throwBizException(ErrorCodeEnum.BO_LIST_ERROR);
        }

        // 根据询价商品id进行排序
        inquiryGoodsBOList.getData().getData().sort(Comparator.comparing(goods -> String.valueOf(goods.get("id"))));

        // 获取当前用户登录信息
        UserDto currentUser = UserUtils.getCurrentUser();
        String currentMemberName = "";
        String currentMemberAddress = "";
        String currentMemberPhone = "";
        if (!CollectionUtils.isEmpty(currentUser.getOrganization_id())) {
            if (currentUser.getOrganization_id().get(0).getId().equals(PlatformConst.ORGANIZATION_ID)) {
                // 获取用户设置的默认信息
                List<Map<String, Object>> defaultAddressList = Objects.requireNonNull(JdbcTemplateUtils.builder(AppConst.PERSONAL_CENTER, ModelConst.T_MEMBER_DELIVER_ADDRESS)
                        .selectField("*"))
                        .eq("default_address", 1)
                        .eq("member_id -> '$.id'", currentUser.getId())
                        .queryForList();
                if (!CollectionUtils.isEmpty(defaultAddressList)) {
                    currentMemberName = String.valueOf(defaultAddressList.get(0).get("receiver_name"));
                    currentMemberAddress = defaultAddressList.get(0).get("alias") + String.valueOf(defaultAddressList.get(0).get("address"));
                    currentMemberPhone = String.valueOf(defaultAddressList.get(0).get("mobile"));
                }
            }
        }

        // 设置报表导出数据
        Map<String, Object> reportMap;
        Map<String, Object> inquiryMap = inquiryBO.getData().getData();
        String organizationId = ((List<SelectorFormat>)inquiryMap.get("organization_id")).get(0).getId();
        OrganizationDto organization = OrgUtils.getOrgByOrgId(organizationId);

        List<Map<String,Object>> quotationGoodsList;
        for (Map<String, Object> inquiryGoods : inquiryGoodsBOList.getData().getData()) {
            reportMap = Maps.newHashMap();
            reportMap.put("currentMemberName", currentMemberName);
            reportMap.put("currentMemberAddress", currentMemberAddress);
            reportMap.put("currentMemberPhone", currentMemberPhone);

            reportMap.put("inquiryID", inquiryId);
            reportMap.put("inquiryName", String.valueOf(inquiryMap.get("name")));
            reportMap.put("customerName", String.valueOf(inquiryMap.get("member_name")));
            reportMap.put("connect", String.valueOf(inquiryMap.get("contacts")));
            reportMap.put("phone", String.valueOf(inquiryMap.get("mobile")));
            reportMap.put("expire", String.valueOf(inquiryMap.get("expire")));
            reportMap.put("memo", String.valueOf(inquiryMap.get("memos")));
            reportMap.put("quoteEndTime", String.valueOf(inquiryMap.get("quote_min_time_strategy")));
            reportMap.put("organizationCompanyName", String.valueOf(inquiryMap.get("organization_company_name")));

            reportMap.put("item", String.valueOf(inquiryGoods.get("id")));
            String description = StringUtils.trimWhitespace(String.valueOf(inquiryGoods.get("name"))) + "" +
                    StringUtils.trimWhitespace(String.valueOf(inquiryGoods.get("brand"))) + "" + StringUtils.trimWhitespace(String.valueOf(inquiryGoods.get("model"))) + "" +
                    StringUtils.trimWhitespace(inquiryGoods.get("spec") == null ? "" : String.valueOf(inquiryGoods.get("spec"))) + "" +
                    StringUtils.trimWhitespace(inquiryGoods.get("description") == null ? "" : String.valueOf(inquiryGoods.get("description"))) + "" +
                    StringUtils.trimWhitespace(inquiryGoods.get("sku") == null ? "" : String.valueOf(inquiryGoods.get("sku")));
            reportMap.put("description", description);
            reportMap.put("sku", String.valueOf(inquiryGoods.get("sku")));
            reportMap.put("num", inquiryGoods.get("num") == null ? 0d : ((BigDecimal) inquiryGoods.get("num")).doubleValue());
            reportMap.put("name", String.valueOf(inquiryGoods.get("name")));
            reportMap.put("brand", String.valueOf(inquiryGoods.get("brand")));
            reportMap.put("spec", String.valueOf(inquiryGoods.get("spec")));
            reportMap.put("model", String.valueOf(inquiryGoods.get("model")));
            reportMap.put("unit", String.valueOf(inquiryGoods.get("unit")));
            reportMap.put("time", DateUtils.format2DateStr2(new Date()));
            reportMap.put("clientPurchaseRequest", String.valueOf(inquiryGoods.get("client_purchase_request")));
            reportMap.put("desc", String.valueOf(inquiryGoods.get("description")));

            //密封报价，询价未过期，报表导出不显示
            if ("1".equals(String.valueOf(inquiryMap.get("quote_hermetic_strategy"))) &&
                    DateUtils.parseDate(String.valueOf(inquiryMap.get("expire"))).compareTo(new Date()) > 0) {
                continue;
            }

            //  通过询价商品id获取报价商品列表
            quotationGoodsList = BoServiceUtils.findListBySimple(ModelConst.T_QUOTATION_GOODS, "inquiry_goods_id", inquiryGoods.get("id")).getData().getData();
            log.info("-----------------------通过询价商品id获取报价商品列表：{}------------------------", inquiryGoodsBOList);

            // 移除未报价的商品
            quotationGoodsList.removeIf(quotationGoods -> quotationGoods.get("price") == null);

            // 根据含税单价进行排序
            quotationGoodsList.sort(Comparator.comparing(quotationGoods -> (BigDecimal)quotationGoods.get("price")));

            // 小规模供应商价格转换
            quotationGoodsList = inquiryService.conversion(quotationGoodsList);

            for (Map<String, Object> quotationGoods : quotationGoodsList) {
                if (QuotationStatusEnum.QUOTATION_5_PICKETED.getCode().equals(quotationGoods.get("quotation_goods_status"))) {
                    reportMap.put("preAmount", BigDecimalUtils.mul(quotationGoods.get("pretax_price"), quotationGoods.get("num")));
                    reportMap.put("amount", BigDecimalUtils.mul(quotationGoods.get("price"), quotationGoods.get("num")));
                    reportMap.put("selectVendor", "(已定标)" + quotationGoods.get("vendor_organization_name"));
                    reportMap.put("selectDelivery", quotationGoods.get("delivery") == null ? 0 : ((BigDecimal) quotationGoods.get("delivery")).intValue());
                    reportMap.put("selectRemark", String.valueOf(quotationGoods.get("description")));
                    reportMap.put("selectPrice",quotationGoods.get("price") == null ? 0d : ((BigDecimal) quotationGoods.get("price")).doubleValue());
                    reportMap.put("selectPretaxPrice",quotationGoods.get("pretax_price") == null ? 0d : ((BigDecimal) quotationGoods.get("pretax_price")).doubleValue());
                    break;
                } else {
                    reportMap.put("preAmount", BigDecimalUtils.mul(quotationGoodsList.get(0).get("pretax_price"), quotationGoodsList.get(0).get("num")));
                    reportMap.put("amount", BigDecimalUtils.mul(quotationGoodsList.get(0).get("price"), quotationGoodsList.get(0).get("num")));
                    reportMap.put("selectVendor", String.valueOf(quotationGoodsList.get(0).get("vendor_organization_name")));
                    reportMap.put("selectDelivery", quotationGoodsList.get(0).get("delivery") == null ? 0 : ((BigDecimal) quotationGoodsList.get(0).get("delivery")).intValue());
                    reportMap.put("selectRemark", String.valueOf(quotationGoodsList.get(0).get("description")));
                    reportMap.put("selectPrice",quotationGoodsList.get(0).get("price") == null ? 0d : ((BigDecimal) quotationGoodsList.get(0).get("price")).doubleValue());
                    reportMap.put("selectPretaxPrice",quotationGoodsList.get(0).get("pretax_price") == null ? 0d : ((BigDecimal) quotationGoodsList.get(0).get("pretax_price")).doubleValue());
                }
            }
            if (quotationGoodsList.size() > 0) {
                reportMap.put("supplier1", String.valueOf(quotationGoodsList.get(0).get("vendor_organization_name")));
                reportMap.put("price1", BigDecimalUtils.isNull(quotationGoodsList.get(0).get("pretax_price")).doubleValue());
                reportMap.put("hprice1", BigDecimalUtils.isNull(quotationGoodsList.get(0).get("price")).doubleValue());
                reportMap.put("delivery1", BigDecimalUtils.isNull(quotationGoodsList.get(0).get("delivery")).intValue());
                reportMap.put("qnum1", BigDecimalUtils.isNull(quotationGoodsList.get(0).get("num")).doubleValue());
                reportMap.put("qunit1", String.valueOf(quotationGoodsList.get(0).get("unit")));
                reportMap.put("amount1", BigDecimalUtils.isNull(quotationGoodsList.get(0).get("amount")).doubleValue());
                reportMap.put("pamount1", BigDecimalUtils.isNull(quotationGoodsList.get(0).get("pretax_amount")).doubleValue());
                reportMap.put("taxRate1", new BigDecimal(String.valueOf(quotationGoodsList.get(0).get("tax_rate"))).doubleValue());
                reportMap.put("remark", String.valueOf(quotationGoodsList.get(0).get("description")));
                reportMap.put("pretaxPrice1", BigDecimalUtils.isNull(quotationGoodsList.get(0).get("pretax_price")).doubleValue());
                reportMap.put("minOrder1", BigDecimalUtils.isNull(quotationGoodsList.get(0).get("min_order")).doubleValue());
                reportMap.put("memberFullName1", String.valueOf(quotationGoodsList.get(0).get("member_full_name")));
                reportMap.put("memberMobile1", String.valueOf(quotationGoodsList.get(0).get("member_mobile")));
            }
            if (quotationGoodsList.size() > 1) {
                reportMap.put("supplier2", String.valueOf(quotationGoodsList.get(1).get("vendor_organization_name")));
                reportMap.put("price2", BigDecimalUtils.isNull(quotationGoodsList.get(1).get("pretax_price")).doubleValue());
                reportMap.put("hprice2", BigDecimalUtils.isNull(quotationGoodsList.get(1).get("price")).doubleValue());
                reportMap.put("delivery2", BigDecimalUtils.isNull(quotationGoodsList.get(1).get("delivery")).intValue());
                reportMap.put("qnum2", BigDecimalUtils.isNull(quotationGoodsList.get(1).get("num")).doubleValue());
                reportMap.put("qunit2", String.valueOf(quotationGoodsList.get(1).get("unit")));
                reportMap.put("amount2", BigDecimalUtils.isNull(quotationGoodsList.get(1).get("amount")).doubleValue());
                reportMap.put("pamount2", BigDecimalUtils.isNull(quotationGoodsList.get(1).get("pretax_amount")).doubleValue());
                reportMap.put("taxRate2", new BigDecimal(String.valueOf(quotationGoodsList.get(1).get("tax_rate"))).doubleValue());
                reportMap.put("remark2", String.valueOf(quotationGoodsList.get(1).get("description")));
                reportMap.put("pretaxPrice2", BigDecimalUtils.isNull(quotationGoodsList.get(1).get("pretax_price")).doubleValue());
                reportMap.put("minOrder2", BigDecimalUtils.isNull(quotationGoodsList.get(1).get("min_order")).doubleValue());
                reportMap.put("memberFullName2", String.valueOf(quotationGoodsList.get(1).get("member_full_name")));
                reportMap.put("memberMobile2", String.valueOf(quotationGoodsList.get(1).get("member_mobile")));
            }
            if (quotationGoodsList.size() > 2) {
                reportMap.put("supplier3", String.valueOf(quotationGoodsList.get(2).get("vendor_organization_name")));
                reportMap.put("price3", BigDecimalUtils.isNull(quotationGoodsList.get(2).get("pretax_price")).doubleValue());
                reportMap.put("hprice3", BigDecimalUtils.isNull(quotationGoodsList.get(2).get("price")).doubleValue());
                reportMap.put("delivery3", BigDecimalUtils.isNull(quotationGoodsList.get(2).get("delivery")).intValue());
                reportMap.put("qnum3", BigDecimalUtils.isNull(quotationGoodsList.get(2).get("num")).doubleValue());
                reportMap.put("qunit3", String.valueOf(quotationGoodsList.get(2).get("unit")));
                reportMap.put("amount3", BigDecimalUtils.isNull(quotationGoodsList.get(2).get("amount")).doubleValue());
                reportMap.put("pamount3", BigDecimalUtils.isNull(quotationGoodsList.get(2).get("pretax_amount")).doubleValue());
                reportMap.put("taxRate3", new BigDecimal(String.valueOf(quotationGoodsList.get(2).get("tax_rate"))).doubleValue());
                reportMap.put("remark3", String.valueOf(quotationGoodsList.get(2).get("description")));
                reportMap.put("pretaxPrice3", BigDecimalUtils.isNull(quotationGoodsList.get(2).get("pretax_price")).doubleValue());
                reportMap.put("minOrder3", BigDecimalUtils.isNull(quotationGoodsList.get(2).get("min_order")).doubleValue());
                reportMap.put("memberFullName3", String.valueOf(quotationGoodsList.get(2).get("member_full_name")));
                reportMap.put("memberMobile3", String.valueOf(quotationGoodsList.get(2).get("member_mobile")));
            }
            reportMap.put("organizationId", organizationId);

            // 设置需要显示的平台信息
            reportMap.put("platformName", organization.getPlatform_name());
            reportMap.put("platformId", organization.getPlatform_id());
            reportList.add(reportMap);
        }
        return ReportUtils.exportReport(record.getCode(), record.getType(), reportList);
    }
}
